﻿using System;
using System.Collections.Generic;
using GeoAPI.Geometries;

namespace NetTopologySuite.Geometries.Utilities
{
	public class GeometryCombiner
	{
		public static IGeometry Combine(ICollection<IGeometry> geoms)
		{
			return new GeometryCombiner(geoms).Combine();
		}

		public static IGeometry Combine(IGeometry g0, IGeometry g1)
		{
			return new GeometryCombiner(GeometryCombiner.CreateList(g0, g1)).Combine();
		}

		public static IGeometry Combine(IGeometry g0, IGeometry g1, IGeometry g2)
		{
			return new GeometryCombiner(GeometryCombiner.CreateList(g0, g1, g2)).Combine();
		}

		private static List<IGeometry> CreateList(IGeometry obj0, IGeometry obj1)
		{
			return new List<IGeometry>
			{
				obj0,
				obj1
			};
		}

		private static List<IGeometry> CreateList(IGeometry obj0, IGeometry obj1, IGeometry obj2)
		{
			return new List<IGeometry>
			{
				obj0,
				obj1,
				obj2
			};
		}

		public static bool SkipEmpty { get; set; }

		public GeometryCombiner(ICollection<IGeometry> geoms)
		{
			this._geomFactory = GeometryCombiner.ExtractFactory(geoms);
			this._inputGeoms = geoms;
		}

		public static IGeometryFactory ExtractFactory(ICollection<IGeometry> geoms)
		{
			if (geoms.Count == 0)
			{
				return null;
			}
			IEnumerator<IGeometry> enumerator = geoms.GetEnumerator();
			enumerator.MoveNext();
			return enumerator.Current.Factory;
		}

		public IGeometry Combine()
		{
			List<IGeometry> list = new List<IGeometry>();
			foreach (IGeometry geom in this._inputGeoms)
			{
				GeometryCombiner.ExtractElements(geom, list);
			}
			if (list.Count != 0)
			{
				return this._geomFactory.BuildGeometry(list);
			}
			if (this._geomFactory == null)
			{
				return null;
			}
			return this._geomFactory.CreateGeometryCollection(null);
		}

		private static void ExtractElements(IGeometry geom, ICollection<IGeometry> elems)
		{
			if (geom == null)
			{
				return;
			}
			for (int i = 0; i < geom.NumGeometries; i++)
			{
				IGeometry geometryN = geom.GetGeometryN(i);
				if (!GeometryCombiner.SkipEmpty || !geometryN.IsEmpty)
				{
					elems.Add(geometryN);
				}
			}
		}

		private readonly IGeometryFactory _geomFactory;

		private readonly ICollection<IGeometry> _inputGeoms;
	}
}
